package com.hs.utils;

import static java.lang.System.out;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.hs.exception.XMLException;
 

public class XmlParser {
	
	private HashMap map = new HashMap();
	private String keys = "";
	/**
	 * main函数测试
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			//文件构造
			XmlParser ps = new XmlParser("3.xml");
			out.println( "\n<"+ps.get("专利权人:地址")+">" );
			out.println("\n******************************************\n");
			//流构造
			XmlParser pss = new XmlParser ( new FileInputStream("3.xml") );
			out.println( "\n<"+pss.get("联系人:姓名")+">" );
		} catch (XMLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	/**
	 * 私有构造函数，防止未初始化文件就取值
	 */
	private XmlParser() {
	}
	/**
	 * 文件构造函数
	 * @param xmlname
	 * @throws XMLException
	 */
	public XmlParser(String xmlname) throws XMLException {
		parseDocument(xmlname,null);
	}
	/**
	 * IO流构造函数
	 * @param is
	 * @throws XMLException
	 */
	public XmlParser(InputStream is) throws XMLException {
		parseDocument(null,is);
	}

	/**
	 * //解析Document
	 * 
	 * @param xmlname 为xml文件名称
	 *           
	 */
	private void parseDocument(String xmlname,InputStream is) throws XMLException {
		
		try {
			DocumentBuilderFactory domfac = DocumentBuilderFactory
					.newInstance();

			DocumentBuilder dombuilder = domfac.newDocumentBuilder();
			if(is == null)
				is = new FileInputStream(xmlname);			
			Document doc = dombuilder.parse(is);
			parseNode(doc, "");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			throw new XMLException("xml文件不存在");
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			throw new XMLException(e.getMessage());
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			throw new XMLException(e.getMessage());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			throw new XMLException(e.getMessage());
		} finally {
			try {
				if (is != null)
					is.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				throw new XMLException("xml文件关闭异常");
			}
		}
	}
	/**
	 * 对节点递归解析
	 * @param n 节点对象
	 * @param indent
	 */
	private void parseNode(Node n, String indent) {
		short type = n.getNodeType();
		// out.println("type==>"+type+"<==end");
		switch (type) {
		case Node.DOCUMENT_NODE:
			// out.println("<?xml version='1.0' encoding='gb2312'?>");
			Document doc = (Document) n;
			NodeList nl = doc.getChildNodes();
			if (nl != null) {
				int len = nl.getLength();
				for (int i = 0; i < len; i++)
					parseNode(nl.item(i), "");
			}
			break;
		case Node.ELEMENT_NODE:
			Element e = (Element) n;
			// out.print("<" + e.getNodeName());
			// key = e.getNodeName()+key;
			NamedNodeMap attrs = e.getAttributes();
			if (attrs != null) {
				int len = attrs.getLength();
				for (int i = 0; i < len; i++) {
					parseNode(attrs.item(i), "");
				}
			}
			// out.print(">");
			NodeList enl = e.getChildNodes();
			if (enl != null) {
				int len = enl.getLength();
				indent += " ";
				for (int i = 0; i < len; i++)
					parseNode(enl.item(i), indent);
				if(len==0){
					map.put(getKey("",n), "");
					//out.print("[" + getKey("", n) + "]=" + "[]\n");
				}
			}
			// out.print("</" + e.getNodeName() + ">");
			break;
		case Node.ATTRIBUTE_NODE:
			Attr atr = (Attr) n;
			// out.print(" " + atr.getName() + "='" + atr.getNodeValue() + "'");
			break;
		case Node.TEXT_NODE:
			//out.print(n.getNodeValue());
			String value = n.getNodeValue();	
			String key = getKey("", n);			
			if (value.trim().equals(""))
				value = "";
			if(key!=null&& !key.equals("")){
				if( map.get(key)==null  ){
					map.put(key, value);
					//out.print("[" + getKey("", n) + "]=" + "[" + value + "]\n");					
				}
			}
		}
	}
	/**
	 * 取节点的名称 规则为 【 跟节点：父节点：子结点 】
	 * @param key
	 * @param node
	 * @return
	 */
	private String getKey(String key, Node node) {
		Node temp = node.getParentNode();
		if (temp != null) {
			if ("".equals(key))
				keys = node.getNodeName();
			else
				keys = node.getNodeName() + ":" + key;
			getKey(keys, temp);
		}
		if(keys.indexOf("#")==-1){//说明此节点值为""
			return keys.substring(keys.indexOf(":") + 1); 
		}		
		if (keys.substring(keys.indexOf(":") + 1).startsWith("#"))//说明此节点的值为#text
			return null;
		return keys.substring(keys.indexOf(":") + 1, keys.indexOf("#") - 1); // 返回从二级节点开始的节点名称
	}
	/**
	 * 对外开放函数取对应节点的值
	 * @param key
	 * @return
	 */
	public String get(String key) {
		out.println(map);
		if( map.get(key) != null) 
			return map.get(key).toString();
		return null;
	}
	/**
	 * 留有put接口存放值
	 * @param key
	 * @param value
	 */
	public void put(String key,String value) {
		map.put(key, value);
	}
}